package com.ldzhao.blog.web.controller;

import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.primitives.Ints;
import com.ldzhao.blog.event.EventBus;
import com.ldzhao.blog.event.VisitEventConsumer;
import com.ldzhao.blog.model.entity.Config;
import com.ldzhao.blog.model.entity.GeoInfo;
import com.ldzhao.blog.model.vo.VisitorVo;
import com.ldzhao.blog.service.SysConfigService;
import com.ldzhao.blog.util.BaiduUtil;
import com.ldzhao.blog.util.DateUtil;
import com.ldzhao.blog.util.UrlBuildUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <ClassName>VisitorController</ClassName>
 * <Description></Description>
 *
 * @Author liuxianzhao
 * @Date 2018年07月22日 09:52
 */
@Controller
@RequestMapping("/visitor")
@Slf4j
public class VisitorController {
    @Resource
    private RedisTemplate redisTemplate;
    @Autowired
    private SysConfigService configService;

    @RequestMapping("/")
    public String index(Model model) {
        Set<String> visitAllIp = Optional.ofNullable(redisTemplate.opsForSet().members("visitAll_ip")).orElse(Sets.newHashSet());
        Config config = configService.get();
        Map<String, Integer> visitLocation = Maps.newTreeMap();
        List<VisitorVo> visitorVoList = Lists.newArrayListWithExpectedSize(visitAllIp.size());
        Map<String, String> ipInfo = Maps.newTreeMap();
        visitAllIp.stream().forEach(ip -> {
            try {
                GeoInfo locationJson = BaiduUtil.getLocationInfo(UrlBuildUtil.getLocationByIp(ip, config.getBaiduApiAk()), ip);
                if (locationJson != null && "0".equals(locationJson.getStatus())) {
                    GeoInfo.Content content = locationJson.getContent();
                    GeoInfo.Detail address_detail = content.getAddress_detail();
                    String city = address_detail.getCity();
                    String province = address_detail.getProvince();
                    String location = "中国 " + province + " " + city;
                    Integer ipnum = visitLocation.get(location);
                    if (ipnum == null) {
                        visitLocation.put(location, 1);
                    } else {
                        visitLocation.put(location, ipnum + 1);
                    }
                    ipInfo.put(ip, location);
                    // 经纬度
                    GeoInfo.Point point = content.getPoint();
                    // 纬度
                    String lat = point.getY();
                    // 经度
                    String lng = point.getX();
                    visitorVoList.add(VisitorVo.create(location, lat, lng));
                }
            } catch (Exception e) {
            }
        });
        List<Tuple2<String, Integer>> collect = visitLocation.entrySet()
                .stream()
                .map(entry -> Tuples.of(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
        Collections.sort(collect, (o1, o2) -> -Ints.compare(o1.getT2(), o2.getT2()));
        int size = collect.size();
        List<String> topList = collect.subList(0, Math.min(size, 10)).stream().map(t -> t.getT1()).collect(Collectors.toList());
        model.addAttribute("topList", topList);
        model.addAttribute("visitorVoList", JSONArray.toJSONString(visitorVoList));
        return "/visitor";
    }

    @GetMapping("/analyze")
    @ResponseBody
    public Map<String, Object> visitAnalyze() {
        String today = DateUtil.date2Str(new Date(), "yyyyMMdd");
        Set<String> visitTodayIp = Optional.ofNullable(redisTemplate.opsForSet().members("visitToday_ip_" + today)).orElse(Sets.newHashSet());
        Config config = configService.get();
        Map<String, Object> result = Maps.newHashMap();
        Map<String, Integer> visitLocation = Maps.newTreeMap();

        Map<String, String> ipInfo = Maps.newTreeMap();
        visitTodayIp.stream().forEach(ip -> {
            try {
                GeoInfo locationJson = BaiduUtil.getLocationInfo(UrlBuildUtil.getLocationByIp(ip, config.getBaiduApiAk()), ip);
                String location = null;
                if (locationJson != null) {
                    GeoInfo.Content content = locationJson.getContent();
                    if ("0".equals(locationJson.getStatus())) {
                        GeoInfo.Detail address_detail = content.getAddress_detail();
                        String city = address_detail.getCity();
                        String province = address_detail.getProvince();
                        location = "中国 " + province + " " + city;
                    } else {
                        location = locationJson.getAddress();
                    }
                } else {
                    location = "unknow";
                }
                Integer ipnum = visitLocation.get(location);
                if (ipnum == null) {
                    visitLocation.put(location, 1);
                } else {
                    visitLocation.put(location, ipnum + 1);
                }
                ipInfo.put(ip, location);
            } catch (Exception e) {
            }
        });
        result.put("num", visitTodayIp.size());
        result.put("visitLocation", visitLocation);
        result.put("ipInfo", ipInfo);
        return result;
    }

    @RequestMapping("event")
    public void event(HttpServletRequest request, HttpServletResponse response) {
        VisitEventConsumer consumer = new VisitEventConsumer(response);
        try {
            EventBus.getInstance().register(consumer);
            consumer.checkException();
        } catch (Exception e) {
            log.error("event异常", e);
        } finally {
            consumer.deprecated();
            try {
                response.getOutputStream().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
